package simpleparser

import (
	"errors"
	"fmt"
)

func Parse(tokenList *TokenList) (ret *AstNode, err error) {
	ret, err = matchIntDeclare(tokenList)
	if err == nil {
		return ret, nil
	}

	ret, err = matchAddExpression(tokenList)
	if err == nil {
		return ret, nil
	}

	return ret, err
}

func matchIntDeclare(tokenList *TokenList) (*AstNode, error) {
	var root *AstNode = nil

	pos := tokenList.getPosition()

	token := tokenList.Peek()
	if token.Type != INT {
		return root, errors.New("Expected integer identifier")
	}
	tokenList.Next()

	token = tokenList.Peek()
	if token == nil || token.Type != ID {
		tokenList.setPosition(pos)
		return root, errors.New("Expected identifier")
	}
	tokenList.Next()

	root = &AstNode{Type: DeclareInt, Value: token.Value}

	token = tokenList.Peek()
	if token == nil || token.Type != ASSIGNMENT {
		tokenList.setPosition(pos)
		return root, errors.New("Expected assignment")
	}
	tokenList.Next()

	newNode, err := matchAddExpression(tokenList)
	if err != nil {
		tokenList.setPosition(pos)
		return root, err
	}

	root.Children = append(root.Children, newNode)
	return root, nil
}

func matchAddExpression(tokenList *TokenList) (*AstNode, error) {
	var root *AstNode = nil

	pos := tokenList.getPosition()

	newNode, err := matchMultiExpression(tokenList)
	if err != nil {
		return root, err
	}

	token := tokenList.Peek()
	if token == nil {
		return newNode, nil
	}

	if token.Type != PLUS {
		return newNode, nil
	}
	tokenList.Next()

	root = &AstNode{Type: ExprAdd, Value: token.Value}

	newNode2, err := matchAddExpression(tokenList)
	if err != nil {
		tokenList.setPosition(pos)
		return root, err
	}

	root.Children = append(root.Children, newNode)
	root.Children = append(root.Children, newNode2)

	return root, nil
}

func matchMultiExpression(tokenList *TokenList) (*AstNode, error) {
	var root *AstNode = nil

	pos := tokenList.getPosition()

	newNode, err := matchToken(tokenList, INTLITERAL)
	if err != nil {
		return root, err
	}

	// 只有一个参数
	token := tokenList.Peek()
	if token == nil {
		return newNode, nil
	}

	if token.Type != STAR {
		return newNode, nil
	}
	tokenList.Next()

	root = &AstNode{Type: ExprMul, Value: token.Value}

	newNode2, err := matchMultiExpression(tokenList)
	if err != nil {
		tokenList.setPosition(pos)
		return root, err
	}

	root.Children = append(root.Children, newNode)
	root.Children = append(root.Children, newNode2)

	return root, nil
}

func matchToken(tokenList *TokenList, t TokenType) (*AstNode, error) {
	token := tokenList.Peek()
	if token != nil && token.Type == t {
		tokenList.Next()
		return &AstNode{Type: LiteralInt, Value: token.Value}, nil
	} else {
		return nil, errors.New(fmt.Sprintf("Expected %v, got %v", t, token))
	}
}
